package cn.htsyb.synergy.security.controller;

import cn.htsyb.synergy.model.ApiResult;
import cn.htsyb.synergy.orm.constant.DeleteMode;
import cn.htsyb.synergy.orm.jpa.criterion.OrderExpress;
import cn.htsyb.synergy.orm.jpa.criterion.QueryExpress;
import cn.htsyb.synergy.orm.jpa.model.param.PageParam;
import cn.htsyb.synergy.security.bean.param.SecurityUserParam;
import cn.htsyb.synergy.security.entity.SecurityUser;
import cn.htsyb.synergy.security.service.ISecurityUserService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * 用户 接口
 * codeMaker at 2020-07-14
 * @author lakeside hubin_yuan.410@hotmail.com
 * @since 2020-07-14
 */
@Slf4j(topic = "security")
@RestController(value = "SecurityUserRestController")
@RequestMapping(value = {"/security/user"} )
@Tag(name = "SecurityUserRestController",description ="用户接口" )
public class SecurityUserRestController {
    @Autowired
    protected ISecurityUserService securityUserService;
    ObjectMapper objectMapper = new ObjectMapper();
    /**
    * 默认排序
    * @return
    */
    private  List<OrderExpress> defaultOrderBy(){
        return new ArrayList<OrderExpress>(){{
            this.add(new OrderExpress("id" , OrderExpress.Direction.DESC));
        }} ;
    }
    /**
    * 添加【我的】条件
    * @return
    */
    private  List<QueryExpress> addMineCriterion(List<QueryExpress> searchBys){
        //searchBys.add(new QueryExpress("created_by", OperatorEnum.EQ,SecurityContextUtil.getCurrentAuthUserId()));
        return searchBys;
    }
    @Operation(summary  = "统计数量查询" )
    @GetMapping(value = "/count" )
    public ApiResult<Long> countSearch(SecurityUserParam securityUserParam) {
        try {
            Long  countSize = securityUserService.countAll(addMineCriterion(securityUserParam.searchCriterion()), securityUserParam.filterCriterion());
            return ApiResult.instance(countSize);
        } catch (Exception ex) {
            log.error("统计数量查询" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "获取对象信息" )
    @GetMapping(value = "/{idArr}" )
    public ApiResult<SecurityUser> findById(@PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr) {
        try {
            if(idArr.size()==1){
                SecurityUser securityUser=securityUserService.findById (idArr.get(0));
                Assert.notNull(securityUser ,"实体对象不存在");
                return new ApiResult(securityUser);
            }else{
                List<SecurityUser> securityUserList=  securityUserService.findAllByIds(idArr);
                return new ApiResult(securityUserList);
            }
        } catch (Exception ex) {
            log.error("获取对象信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "分页查询信息" )
    @GetMapping(value = "/page" )
    @ResponseBody
    public ApiResult<Page<SecurityUser>> pageSearch(PageParam pageParam, SecurityUserParam securityUserParam) {
        try {
            List<OrderExpress> orderBys= OrderExpress.parseOrderParam( pageParam.getOrder());
            if(CollectionUtils.isEmpty(orderBys)){orderBys=defaultOrderBy();}
            Page<SecurityUser> pageResult = securityUserService.findAllPage(
                    addMineCriterion(securityUserParam.searchCriterion()),
                    securityUserParam.filterCriterion(),orderBys,pageParam);
            return ApiResult.instance(pageResult);
        } catch (Exception ex) {
            log.error("分页查询实体出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }

    @Operation(summary = "列表查询信息" )
    @GetMapping(value = "/list" )
    public ApiResult<Collection<SecurityUser>> listSearch(SecurityUserParam securityUserParam) {
        try {
            Collection<SecurityUser> listResult = securityUserService.findAllList(
                    addMineCriterion(securityUserParam.searchCriterion()),
                    securityUserParam.filterCriterion(),defaultOrderBy());
            return new ApiResult(listResult);
        } catch (Exception ex) {
            log.error("查询实体列表出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAnyAuthority({'security:user:add','security:user:edit'})")
    @Operation(summary = "批量保存实体信息（全量插入）" , description = "批量保存实体信息（更新面向实体，全量插入）" )


    @PostMapping(value = "/save" )
    public ApiResult<?> saveBatch( @RequestBody @NotNull JsonNode filedJsonNode) {
        try {
            if(filedJsonNode.isArray()){
                List<SecurityUser> securityUserList=objectMapper.readValue(filedJsonNode.toString(),new TypeReference<List<SecurityUser>>() {});
                return ApiResult.instance(securityUserService.saveAllEntity(securityUserList));
            }else{
                SecurityUser securityUser=objectMapper.readValue(filedJsonNode.toString(),SecurityUser.class);
                return ApiResult.instance(securityUserService.saveEntity(securityUser));
            }
        } catch (Exception ex) {
            log.error("保存实体信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAuthority('security:user:edit')")
    @Operation(summary = "批量更新实体部分字段信息" , description = "批量更新实体的字段信息(更新面向字段，未传字段不更新))" )

    @PutMapping(value = "/{idArr}" )
    public ApiResult<List<SecurityUser>> patchBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @NotNull @RequestBody JsonNode filedJsonNode) {
        try {
            Assert.isTrue( !filedJsonNode.has("id"),"更新字段中不能存在主键编号字段");
            Assert.isTrue( !filedJsonNode.isArray(),"不能使用数组设置更新字段");
            List<SecurityUser> securityUserList=  securityUserService.findAllByIds(idArr);
            for (SecurityUser securityUser:securityUserList) {
                objectMapper.readerForUpdating(securityUser).readValue(filedJsonNode);
            }
                securityUserService.saveAllEntity(securityUserList);
            return ApiResult.instance(securityUserList);
        } catch (Exception ex) {
            log.error("更新实体字段信息出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
    @PreAuthorize("hasAuthority('security:user:del')")
    @Operation(summary = "实体删除" )
    @DeleteMapping(value = "/{idArr}" )
    public ApiResult<List<String>> deleteBatch(
            @PathVariable @Parameter(description = "记录主键，多个记录使用【,】分割", required = true) List<String> idArr,
            @RequestParam(required = false, defaultValue = "logical" ) @Parameter(description = "删除模式", required = true) DeleteMode deleteMode) {
        try {
            securityUserService.deleteByIds(idArr,deleteMode);

            return ApiResult.instance(idArr);
        } catch (Exception ex) {
            log.error("实体删除出现错误" , ex);
            return ApiResult.instance(400,ex.getMessage());
        }
    }
}
